package com.jackeysun.common

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.graphics.drawable.BitmapDrawable
import android.os.Bundle
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.text.style.ImageSpan
import android.text.style.URLSpan
import android.util.Base64
import android.util.Base64.decode
import android.view.View
import android.widget.TextView
import androidx.fragment.app.FragmentActivity
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestOptions
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import net.nightwhistler.htmlspanner.HtmlSpanner
import net.nightwhistler.htmlspanner.TagNodeHandler
import org.htmlcleaner.TagNode
import java.util.concurrent.TimeUnit

/**
 *   Created by sunxunchao on 2021/11/17.
 */
suspend fun TextView.showRich(html: String?) {
    showRich(html, null, null)
}

suspend fun TextView.showRich(html: String?, tag: String?, handler: TagNodeHandler?) {
    val mHtmlSpanner = HtmlSpanner()
    if (!tag.isNullOrEmpty() && handler != null) {
        mHtmlSpanner.registerHandler(tag, handler)
    }
    mHtmlSpanner.registerHandler("a", AHandlerSelf())
    this.movementMethod = LinkMovementMethod.getInstance()
    this.text = html?.fromHtml(mHtmlSpanner)
}

suspend fun String.fromHtml(mHtmlSpanner: HtmlSpanner): Spannable {
    return withContext(Dispatchers.IO) {
        mHtmlSpanner.fromHtml(this@fromHtml)
    }
}

/**
 * a标签中 ”href“属性值为空的情况
 */
class AHandlerSelf : TagNodeHandler() {
    override fun handleTagNode(
        node: TagNode?,
        builder: SpannableStringBuilder?,
        start: Int,
        end: Int
    ) {
        val href = node?.getAttributeByName("href")
        if (!href.isNullOrEmpty()) {
            builder?.setSpan(
                URLSpan(href), start, end,
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
            )
        }
    }

}

class ImageHandlerSelf(val activity: FragmentActivity, val width: Int) :
    TagNodeHandler() {
    override fun handleTagNode(
        node: TagNode?,
        builder: SpannableStringBuilder?,
        start: Int,
        end: Int
    ) {

        val src = node?.getAttributeByName("src") ?: ""
        val item = "\uFFFC"
        builder?.append(item)
        val endTo = end + item.length
        builder?.let {

            try {
                if (src.startsWith("data:image")) {
                    val decodedString = decode(src.split(",")[1], Base64.DEFAULT)
                    val bitmap = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.size)
                    val scale = (width.toFloat() / bitmap.width)
                    val resource = BitmapDrawable(activity.resources, bitmap scaleTo scale)
                    resource.setBounds(0, 0, width, bitmap.height.times(scale).toInt())
                    builder.setSpan(
                        ImageSpan(resource), start, endTo,
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
                    )
                } else {
                    val file =
                        Glide.with(activity).asFile().load(src).submit().get(5, TimeUnit.SECONDS)
                    val options = BitmapFactory.Options()
                    options.inJustDecodeBounds = true
                    BitmapFactory.decodeFile(file.absolutePath, options)
                    val w = options.outWidth
                    val h = options.outHeight
                    val factor = if (h == 0) {
                        3 / 2f
                    } else {
                        w / h.toFloat()
                    }
                    val height = (width / factor).toInt()
                    val glideOptions = RequestOptions()
                        .skipMemoryCache(true)
                        .diskCacheStrategy(DiskCacheStrategy.NONE)
                        .centerInside()
                        .override(width, height)
                    val resource =
                        Glide.with(activity).asDrawable().load(file).apply(glideOptions).submit()
                            .get(5, TimeUnit.SECONDS)
                    resource.setBounds(0, 0, width, height)
                    builder.setSpan(
                        ImageSpan(resource), start, endTo,
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
                    )
                }
                val clickImage = object : ClickableSpan() {
                    override fun onClick(widget: View) {
                        val dialog = DialogFragmentShowPic()
                        val bundle = Bundle()
                        bundle.putString("content", src)
                        dialog.arguments = bundle
                        dialog.show(
                            activity.supportFragmentManager,
                            "DialogFragmentJKRealTestShowPic"
                        )
                    }
                }
                builder.setSpan(
                    clickImage, start, endTo,
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
                )

            } catch (e: Throwable) {
                e.printStackTrace()
            }
        }

    }
}

private infix fun Bitmap.scaleTo(ratio: Float): Bitmap? {
    val width = this.width
    val height = this.height
    val matrix = Matrix()
    matrix.preScale(ratio, ratio)
    val newBM = Bitmap.createBitmap(this, 0, 0, width, height, matrix, false)
    if (newBM == this) {
        return newBM
    }
    this.recycle()
    return newBM
}



